package com.qys.wallet.pay.hyperbc;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.qys.wallet.pay.hyperbc.dto.req.AddressReqDTO;
import com.qys.wallet.pay.hyperbc.dto.resp.AddressDTO;
import com.qys.wallet.pay.hyperbc.dto.resp.BaseRespDTO;
import com.qys.wallet.pay.hyperbc.dto.resp.CoinTypeDTO;
import com.qys.wallet.pay.hyperbc.dto.resp.ExchangeDTO;
import com.qys.wallet.pay.hyperbc.util.RsaSignerUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class HyperbcService {

    /**
     * 配置
     */
    private final HyperbcConfig hyPayConfig;


    private BaseRespDTO createParams(Map<String, Object> map, String api) {
        Map<String, Object> params = hyPayConfig.initParams(map);
        log.info("params------>" + params);
        String res = null;
        try {
            params.put("sign", RsaSignerUtils.genSign(params, hyPayConfig.getPriKey()));
            String url = hyPayConfig.getGateway() + api;
            log.info("请求地址------>" + url);
            res = HttpUtil.post(url, JSONObject.toJSONString(params));
            log.info("获取返回结果------>" + res);
            if (null == res) {
                log.error("连接地址服务超时！！！");
                throw new RuntimeException("http error");
            }
            //TODO  当提供给第三方签名正确时 请打开此签名认证 否则不安全
//            JsonObject respObject = JsonParser.parseString(res).getAsJsonObject();
//            if (!RsaSignerUtils.verifySign(respObject, respObject.get("sign").getAsString(), hyPayConfig.getHyPubKey())) {
//                log.error("验证签名错误！！！");
//                throw new RuntimeException("verify response sign fail");
//            }
            BaseRespDTO baseRespDTO = JSONObject.parseObject(res, BaseRespDTO.class);
            System.out.println("获取地址dto = " + baseRespDTO);
            return baseRespDTO;
        } catch (Exception e) {
            e.printStackTrace();
        }
        throw new RuntimeException("http error");
    }


    private String checkResp(BaseRespDTO respDTO) {
        if (respDTO.getStatus() == 200) {
            return respDTO.getData();
        }
        log.error("响应信息:" + respDTO.getMsg(), ",状态码" + respDTO.getStatus());
        if (respDTO.getStatus() == 500) {
            log.error("地址不足");
            throw new RuntimeException("Failed to obtain the recharge address");
        }
        if (respDTO.getStatus() == 551) {
            log.error("有" + respDTO.getData() + "个已分配未使用地址，请使用完再请求新的地址");
            throw new RuntimeException("Failed to obtain the recharge address");
        }
        if (respDTO.getStatus() == 543) {
            log.error("验证失败！！！");
            throw new RuntimeException("The address is wrong！！！");
        }
        if (respDTO.getStatus() == 565) {
            log.error("币种不支持！！！");
            throw new RuntimeException("The address is wrong！！！");
        }
        throw new RuntimeException("Failed to obtain the recharge address");
    }


    /**
     * 获取充值地址
     */
    public String getAddress(String chainName) {
        Map<String, Object> map = new HashMap<>();
        map.put("coin", chainName);
        List addressList = JSONObject.parseObject(checkResp(createParams(map, API.CREATE_ADDRESS)), List.class);
        log.info("获取地址成功,请求到地址列表为：" + addressList);
        return (String) addressList.get(0);
    }

    /**
     * 查询地址使用状态，地址所属关系
     * isUsed :1=使用 , 2=未使用
     */
    public AddressDTO getAddressList(String chainName, Integer isUsed) {
        Map<String, Object> map = new HashMap<>();
        map.put("coin", chainName);
        map.put("is_used", isUsed);
        return JSONObject.parseObject(checkResp(createParams(map, API.ADDRESS_LIST)), AddressDTO.class);
    }


    /**
     * 状态同步接口
     */
    public void syncAddressStatus(String address, String userId) {
        Map<String, Object> map = new HashMap<>();
        map.put("coin", "trx");
        map.put("address", address);
        map.put("user_id", userId);
        JSONObject object = JSONObject.parseObject(checkResp(createParams(map, API.ADDRESS_SYNC_STATUS)));
        String reAddress = (String) object.get("address");
        String reCoin = (String) object.get("coin");
        log.info("绑定币种：" + reCoin + "绑定地址" + reAddress);
        if (!Objects.equals(reAddress, address) || !Objects.equals(reCoin, "trx")) {
            log.error("返回绑定币种或绑定地址不同！！！");
            throw new RuntimeException("Failed to obtain the recharge address");
        }
        log.info("成功");
    }

    /**
     * 地址有效性验证
     */
    public void checkAddress(String chainName,String address) {
        Map<String, Object> map = new HashMap<>();
        map.put("coin", chainName);
        map.put("address", address);
        checkResp(createParams(map, API.CHECK_ADDRESS));
    }

    /**
     * 提现
     * @param amount
     * @param orderNo
     * @param address
     * @param userId
     * @param coinName
     * @return
     */
    public String transfer(String amount, String orderNo, String address, String userId,String coinName) {
        Map<String, Object> map = new HashMap<>();
        map.put("user_id", userId);
        map.put("coin", coinName);
        map.put("amount", amount);
        map.put("address", address);
        map.put("trade_id", orderNo);
        JSONObject object = JSONObject.parseObject(checkResp(createParams(map, API.TRANSFER)));
        String trade_id = (String) object.get("trade_id");
        if (orderNo.equals(trade_id)){
            log.error("请求订单号为【{}】；返回订单号【{}】",orderNo,trade_id);
            throw new RuntimeException("Failed to obtain the recharge address");
        }
        return trade_id;
    }

    /**
     * 商家支持币种查询
     */
    public CoinTypeDTO supportedCoinType() {
        Map<String, Object> map = new HashMap<>(2);
        map.put("page_size", 50);
        return JSONObject.parseObject(checkResp(createParams(map, API.SUPPORTED_COIN_TYPE)), CoinTypeDTO.class);
    }


    /**
     * 查询兑换汇率
     */
    public ExchangeDTO exchange(String sourceCoin) {
        Map<String, Object> map = new HashMap<>(2);
        map.put("source_coin", sourceCoin);
        map.put("target_coin",  "usdt");
        ExchangeDTO exchangeDTO = JSONObject.parseObject(checkResp(createParams(map, API.EXCHANGE)), ExchangeDTO.class);
        log.info("获取到{}/usdt,兑换汇率为{}",sourceCoin,exchangeDTO.getRate());
        return exchangeDTO;
    }

}
